/*
 * This file is part of the nxlog log collector tool.
 * See the file LICENSE in the source root for licensing terms.
 * Website: http://nxlog.org
 * Author: Botond Botyanszki <botond.botyanszki@nxlog.org>
 */

#include "../../src/common/error_debug.h"
#include "../../src/modules/processor/transformer/csv.h"
#include "../../src/core/nxlog.h"
#include "../../src/core/core.h"
#include "../../src/common/syslog.h"

#define NX_LOGMODULE NX_LOGMODULE_TEST

nxlog_t nxlog;

typedef struct csvpair
{
    const char *csv;
    const char *logline;
} csvpair;
	
const char *invalids[] =
{
    "\"",
    "\"\"\"",
    ",\"",
    "\"aaaa",
    "\"aaaa\",",
    NULL,
};

csvpair from_csv_valids[] =
{
    { "\"daemon\",\"info\",\"1970-10-12 12:49:06\",\"host\",\"app\",\"12345\",\"\"n.\"",
      "<30>Oct 12 12:49:06 host app[12345]: \n." },
    { "\"daemon\",\"info\",\"1970-10-12 12:49:06\",\"host\",\"app\",\"12345\",\"message \"\"quoted string\"\" comma,\"",
      "<30>Oct 12 12:49:06 host app[12345]: message \"quoted string\" comma," },
    { "\"daemon\" ,\"info\",\"1970-10-12 12:49:06\",\"host\",\"app\",\"12345\",\"message \"\"quoted string\"\" comma,\"",
      "<30>Oct 12 12:49:06 host app[12345]: message \"quoted string\" comma," },
    { "\"daemon\", \"info\",\"1970-10-12 12:49:06\",\"host\",\"app\",\"12345\",\"message \"\"quoted string\"\" comma,\"",
      "<30>Oct 12 12:49:06 host app[12345]: message \"quoted string\" comma," },
    { "\"daemon\" , \"info\",\"1970-10-12 12:49:06\",\"host\",\"app\",\"12345\",\"message \"\"quoted string\"\" comma,\"",
      "<30>Oct 12 12:49:06 host app[12345]: message \"quoted string\" comma," },
    { "\"daemon\",\"info\",\"1970-10-12 12:49:06\",\"host\",\"app\", ,\"message \"\"quoted string\"\" comma,\"",
      "<30>Oct 12 12:49:06 host app: message \"quoted string\" comma," },
    { "\"daemon\",\"info\",\"1970-10-12 12:49:06\",\"host\",,,\"message \"\"quoted string\"\" comma,\"",
      "<30>Oct 12 12:49:06 host message \"quoted string\" comma," },
    { "\"kern\",\"err\",\"1970-01-31 00:00:00\",\"localhost\",,,",
      "<3>Jan 31 00:00:00 localhost", },

    { NULL, NULL },
};


csvpair to_csv[] =
{
    { "\"kern\",\"err\",\"2010-01-31 00:00:00\",\"localhost\",,,",
      "<3>2010-01-31 00:00:00 localhost", },
    { "\"user\",\"notice\",\"2010-01-31 00:00:00\",\"localhost\",\"echo\",\"1234\",\"Hello world!\"",
      "<999>2010-01-31 00:00:00 localhost echo[1234]: Hello world!", },
    { "\"user\",\"notice\",\"2010-01-31 00:00:00\",\"localhost\",\"echo\",\"1234\",\"Hello world!\"",
      "<1000>2010-01-31 00:00:00 localhost echo[1234]: Hello world!", },
    { "\"user\",\"crit\",\"2010-01-31 00:00:00\",\"localhost\",\"echo\",\"1234\",\"Hello world!\"",
      "<10>2010-01-31 00:00:00 localhost echo[1234]: Hello world!", },
    { "\"user\",\"crit\",\"2010-01-31 00:00:00\",\"localhost\",\"echo\",\"1234\",",
      "<10>2010-01-31 00:00:00 localhost echo[1234]:", },
    { "\"user\",\"crit\",\"2010-01-31 00:00:00\",\"localhost\",\"echo\",,\"Hello world!\"",
      "<10>2010-01-31 00:00:00 localhost echo: Hello world!", },
    { "\"kern\",\"emerg\",\"2010-01-10 15:01:04\",\"localhost\",\"TAG\",\"0\",\"message0\"",
      "<0>2010-01-10 15:01:04 localhost TAG[0]: message0" },
    { "\"kern\",\"alert\",\"2010-01-10 15:01:04\",\"localhost\",\"TAG\",,\"message0\"",
      "<1>2010-01-10 15:01:04 localhost TAG: message0" },
    { "\"user\",\"crit\",\"2010-01-10 00:00:00\",\"localhost\",,,\"[1234]: Hello world!\"",
      "<10>2010-01-10 00:00:00 localhost [1234]: Hello world!" },
    { "\"user\",\"notice\",\"2010-01-10 00:00:00\",\"localhost\",,,\"[1234]: Hello world!\"",
      "2010-01-10 00:00:00 localhost [1234]: Hello world!" },
    { "\"user\",\"notice\",\"2010-01-10 00:00:00\",\"localhost\",,,\"MODID=NX-GUI; Hello world!\"",
      "2010-01-10 00:00:00 localhost MODID=NX-GUI; Hello world!" },
    { "\"user\",\"notice\",\"2010-01-10 00:00:00\",\"localhost\",,,\"tag[pid]: Hello world!\"",
      "2010-01-10 00:00:00 localhost tag[pid]: Hello world!" },




/*
// default hostname will not work on other hosts, test removed
    { "\"kern\",\"info\",\"Dec  8 16:59:05\",\"mephisto\",\"sh\",\"4780\",\"segfault at 0000000000000000 rip 00002b317bc0e135 rsp 0000000045e73e30 error 6\"",
      "<6>sh[4780]: segfault at 0000000000000000 rip 00002b317bc0e135 rsp 0000000045e73e30 error 6", },
    { "\"user\",\"crit\",\"Jan 31 00:00:00\",\"mephisto\",\"echo\",\"1234\",\"Hello world!\"",
      "<10>Jan 31 00:00:00 echo[1234]: Hello world!", },
    { "\"user\",\"crit\",\"Jan 31 00:00:00\",\"mephisto\",,,\"[1234]: Hello world!\"",
      "<10>Jan 31 00:00:00 [1234]: Hello world!", },
    { "\"kern\",\"err\",\"Jan 31 00:00:00\",\"mephisto\",,,\"[0]\"",
      "<3>Jan 31 00:00:00 [0]", },
*/

    { NULL, NULL },
};

const char *too_many =  "\"daemon\",\"info\",\"Oct 12 12:49:06\",\"host\",\"app\",\"1234\",\"message \"\"quoted string\"\" comma,\", \"xxx\"";
const char *not_enough =  "\"daemon\",\"info\",\"Oct 12 12:49:06\",\"host\",\"app\"";


int main(int argc UNUSED, const char * const *argv, const char * const *env UNUSED)
{
    const char *logline = "<30> 2010-10-12 12:49:06 host app[12345]: message \"quoted string\" comma,";
    const char *csvlogline = "\"daemon\",\"info\",\"2010-10-12 12:49:06\",\"host\",\"app\",\"12345\",\"message \"\"quoted string\"\" comma,\"";
    nx_logdata_t *logdata;
    nx_csv_ctx_t csv_ctx;
    nx_csv_error_t result;
    int i;

    ASSERT(nx_init(&argc, &argv, &env) == TRUE);
    
    memset(&nxlog, 0, sizeof(nxlog_t));
    nxlog_set(&nxlog);
    nxlog.ctx = nx_ctx_new();

    nx_csv_ctx_init(&csv_ctx);
    nx_csv_ctx_set_default_fields(&csv_ctx);

    for ( i = 0; invalids[i] != NULL; i++ )
    {
	logdata = nx_logdata_new_logline(invalids[i], strlen(invalids[i]));
	result = nx_logdata_parse_csv(&csv_ctx, logdata);
	ASSERT(result == NX_CSV_ERROR_INVALID_FORMAT);
	nx_logdata_free(logdata);
    }

    logdata = nx_logdata_new_logline(too_many, strlen(too_many));
    result = nx_logdata_parse_csv(&csv_ctx, logdata);
    ASSERT(result == NX_CSV_ERROR_TOO_MANY_FIELDS);
    nx_logdata_free(logdata);

    logdata = nx_logdata_new_logline(not_enough, strlen(not_enough));
    result = nx_logdata_parse_csv(&csv_ctx, logdata);
    ASSERT(result == NX_CSV_ERROR_INSUFFICIENT_FIELDS);
    nx_logdata_free(logdata);
    
    logdata = nx_logdata_new_logline(logline, strlen(logline));
    ASSERT(nx_syslog_parse_rfc3164(logdata, logdata->data, logdata->datalen) == TRUE);
    nx_logdata_to_csv(&csv_ctx, logdata);
    ASSERT(strcmp(csvlogline, logdata->data) == 0);
    nx_logdata_free(logdata);

    logdata = nx_logdata_new_logline(csvlogline, strlen(csvlogline));
    ASSERT(nx_logdata_parse_csv(&csv_ctx, logdata) == NX_CSV_SUCCESS);
    ASSERT(nx_logdata_to_csv(&csv_ctx, logdata) == NX_CSV_SUCCESS);
    ASSERT(strcmp(logdata->data, csvlogline) == 0);
    nx_logdata_free(logdata);

    for ( i = 0; from_csv_valids[i].csv != NULL; i++ )
    {
	logdata = nx_logdata_new_logline(from_csv_valids[i].csv, strlen(from_csv_valids[i].csv));
	result = nx_logdata_parse_csv(&csv_ctx, logdata);
	ASSERT(result == NX_CSV_SUCCESS);
	ASSERT(nx_logdata_to_syslog_rfc3164(logdata) == TRUE);
	//printf("[%s]\n[%s]\n", logdata->data, from_csv_valids[i].logline);
	ASSERT(strcmp(logdata->data, from_csv_valids[i].logline) == 0);
	nx_logdata_free(logdata);
    }

    for ( i = 0; to_csv[i].csv != NULL; i++ )
    {
	logdata = nx_logdata_new_logline(to_csv[i].logline, strlen(to_csv[i].logline));
	//printf("\n-----------\n");
	nx_syslog_parse_rfc3164(logdata, logdata->data, logdata->datalen);
    	result = nx_logdata_to_csv(&csv_ctx, logdata);
	//nx_logdata_dump_fields(logdata);
	//printf("%s\n%s\n-----------\n", logdata->data, to_csv[i].csv);
	ASSERT(result == NX_CSV_SUCCESS);
	ASSERT(strcmp(logdata->data, to_csv[i].csv) == 0);
	nx_logdata_free(logdata);
    }

    printf("%s:	OK\n", argv[0]);
    return ( 0 );
}
